<?php

require_once 'logsForNewMyPDO.class.php';
require_once 'time.class.php';

/**
 * @author    1054229380@qq.com
 * @since    2017-7-3
 * @desc
 * */
class testPDO
{

    var $_queryTimes = 0; //执行SQL次数
    var $_link = null; //数据链接
    var $_startTime = 0; //开始时间
    var $_endTime = 0; //结束时间
    var $_debug = false; //开启调试(显示所有执行SQL及异常)
    var $_dbType = null; //数据库类型 mysql,sqlsrv
    var $affectedRows = 0;
    var $newInsertId = 0;
    private $_runLog = array();

    function __construct($DbConfig)
    {
        $this->connStr = $DbConfig;
        $this->_dbType = $DbConfig['dbType'];
    }

    /**
     * 数据库连接
     * */
    function connect()
    {
        if (!$this->_link) {
            $DbConfig = $this->connStr;
        } else {
            return;
        }
        if ($this->_debug) {
            $this->_runLog['DBconnectStartTime'][] = time::getMicroTime();
        }
        switch ($DbConfig['dbType']) {
            case "mysql":
                $dbName = $DbConfig['dbType'] . ":host=" . $DbConfig['dbHost'] . ";dbname=" . $DbConfig['dbName'];
                $this->_dbType = "mysql";
                break;

            case "sqlsrv":
                $dbName = "sqlsrv:Server=" . $DbConfig['dbHost'] . ";Database=" . $DbConfig['dbName'];
                $this->_dbType = "sqlsrv";
                break;
        }
        try {
            $pdoObj = new PDO($dbName, $DbConfig['dbUser'], $DbConfig['dbPassWord']);
            $pdoObj->query('set names utf8;');
            $this->_link = $pdoObj;
        } catch (PDOException $e) {
            exit("ERROR:数据库连接异常，请与系统管理员联系！");
        }
    }

    /**
     * 读取表数组
     * @param sql语句 :$sql
     * */
    function getAll($sql)
    {
        $queryObj = $this->query($sql);
        $arr = array();
        if ($queryObj) {
            $queryObj->setFetchMode(PDO::FETCH_ASSOC);
            $arr = array();
            foreach ($queryObj as $rs) {
                $arr[] = $rs;
            }
        }
        return $arr;
    }

    /**
     * 读取表文件缓存数组
     * @param 缓存参数 :$dbCacheArray
     */
    function getFileCacheAll($dbCacheArray)
    {
        $sql = $dbCacheArray['sql'];
        $expireTime = $dbCacheArray['cacheCheckTime'];
        $cacheTriggerName = $dbCacheArray['cacheTriggerName'];
        $cache = new cache();
        $cache->setcachedir("sql"); //设置缓存目录
        $cacheName = md5($sql);
        $fileUrl = $cache->getcacheurl($cacheName, $expireTime, $cacheTriggerName);
        if ($fileUrl == "") {
            $arr = $this->getAll($sql);
            cache::setUpdateTime($cacheTriggerName);
            $cache->setcache($cacheName, $arr);
        } else {
            $arr = $cache->getcache($cacheName);
        }
        return $arr;
    }

    /**
     * @param $sql
     * @return bool
     *
     * 执行SQL语句
     */
    function query($sql)
    {
        $this->connect();
        //$this->affectedRows=0;
        $sqlLog = array();
        $sqlLog = $this->_runLog;
        $starttime = time::getMicroTime(); //开始执行时间
        $this->_queryTimes = $this->_queryTimes + 1;
        try {
            $queryObj = $this->_link->query($sql);
            $endtime = time::getMicroTime(); //结束执行时间
            if (!$queryObj) {//执行异常处理
                $errInfo = $this->_link->errorInfo();
                $_errInfo = $errInfo[2];

                /* 开启调试显示-执行异常 */
                if ($this->_debug) {
                    $_tmpLog['sql'] = $sql;
                    $_tmpLog['msg'] = $_errInfo;
                    $sqlLog['err'][] = $_tmpLog;
                    $this->_runLog = $sqlLog;
                }

                /* 写入错误日志 */
                $errArr['sql'] = $sql;
                $errArr['errorMsg'] = $_errInfo;
                $errArr['postData'] = $_POST;
                logs::write($errArr);
                throw new Exception($_errInfo);
            } else {
                /* 如果执行时间过长,写入异常日志 */
                $runTime = floor(($endtime - $starttime) * 1000); //执行总时间
                if ($runTime > 5000) {
                    $errArr['sql'] = $sql;
                    $errArr['errorMsg'] = "执行时间超长" . $runTime . "毫秒";
                    $errArr['postData'] = $_POST;
                    logs::write($errArr);
                }

                /* 开启调试显示-正常执行 */
                if ($this->_debug) {
                    $_tmpLog['sql'] = $sql;
                    $_tmpLog['msg'] = $runTime;
                    $sqlLog['ok'][] = $_tmpLog;
                    $this->_runLog = $sqlLog;
                }
                //echo $queryObj->rowCount();
                //echo "<br>";
                $this->affectedRows = $queryObj->rowCount();
                $this->newInsertId = $this->_link->lastInsertId();
                return $queryObj;
            }
        } catch (exception $e) {
            return false;
        }
    }

    /**
     * 执行SQL事务
     * @actionType needEffectAll 所有行均有影响才代表成功
     * */
    function queryTransAction($sqlArr, $actionType = '')
    {
        $this->connect();
        $tmpEffectRows = 0;
        $this->_link->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
        try {
            $this->_link->beginTransaction(); // 开启一个事务
            $row = null;
            $sqlNum = count($sqlArr);
            for ($i = 0; $i < $sqlNum; $i++) {
                $row = $this->query($sqlArr[$i]);
                if (!$row) {
                    throw new PDOException("error");
                }
                $tmpEffectRows += $this->affectedRows;
            }
            if ($actionType == 'needEffectAll') {
                if ($tmpEffectRows != $sqlNum) {
                    throw new PDOException("notMacthNum");
                }
            }
            $this->_link->commit();
        } catch (PDOException $e) {
            $this->affectedRows = 0;
            $this->_link->rollback(); // 执行失败，事务回滚
            return false;
        }
        $this->affectedRows = $tmpEffectRows;
        $this->_link->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
        $tmpEffectRows = 0;
        return true;
    }

    function __destruct()
    {
        unset($this->_link); //释放数据链接
        if ($this->_debug) {
            $this->_endTime = time::getMicroTime(); //数据库结束时间
            $this->endMemory = memory_get_usage(); //结束内存占用
            $dbConnectTime = round(($this->_endTime - $this->_startTime), 2); //数据库执行总时间，X秒
            $this->_runLog['allInfo']['runTime'] = $dbConnectTime; //运行时间
            $this->_runLog['allInfo']['queryTimes'] = $this->_queryTimes; //执行次数
            $_startMemory = round($this->startMemory / (1024 * 1214), 2);
            $_endMemory = round($this->endMemory / (1024 * 1024), 2);
            $_usedMemory = round(($_endMemory - $_startMemory), 2);
            $this->_runLog['allInfo']['startMemory'] = $_startMemory; //运行前内存
            $this->_runLog['allInfo']['endMemory'] = $_endMemory; //运行后内存
            $this->_runLog['allInfo']['memoryUsed'] = $_usedMemory; //内存占用
            $showArr = $this->_runLog;
            //e($showArr);
            echo "<div style='text-align:center;margin-top:10px;margin-bottom:10px;font-size:16px;font-weight:600;'>DataBase Query:" . $showArr['allInfo']['queryTimes'] . " &nbsp;&nbsp;RunTime:" . $showArr['allInfo']['runTime'] . "</div>";
            if (isset($showArr['ok'])) {
                for ($i = 0; $i < count($showArr['ok']); $i++) {
                    $how = $i + 1;
                    $sql = $showArr['ok'][$i]['sql'];
                    $sqlRunTime = $showArr['ok'][$i]['msg'];
                    echo "<div style='width:98%;margin:auto;margin-top:10px;margin-bottom:10px;border:1px solid #b5b1b2;padding:5px;background-color:#f3f3f3'>{$how}.{$sql}&nbsp;&nbsp; 执行时间:{$sqlRunTime}</div>";
                }
            }
            if (isset($showArr['err'])) {
                for ($i = 0; $i < count($showArr['err']); $i++) {
                    $how = $i + 1;
                    $sql = $showArr['err'][$i]['sql'];
                    $msg = $showArr['err'][$i]['msg'];
                    echo "<div style='margin-top:10px;margin-bottom:10px;border:1px solid #b5b1b2;padding:5px;background-color:#f3f3f3'>Error: <font style='color:#9e1734'>" . $msg . "</font><br>SQL: <font style='color:#9e1734'>" . $sql . "</font><br></div>";
                }
            }
            unset($this->_runLog);
        }
    }

}

?>